home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DClap / DWindow.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  15.0 KB  |  650 lines  |  [TEXT/R*ch]

  1. // DWindow.cp
  2. // d.g.gilbert
  3.  
  4. #include "Dvibrant.h"
  5. #include "DWindow.h"
  6. #include "DControl.h"
  7. #include "DFindDlog.h"
  8. #include "DList.h"
  9. #include "DApplication.h"
  10. #include "DTask.h"
  11. #include "DMethods.h"
  12.  
  13.  
  14. //
  15. //        Mswin/Borland C++ has some weird problem with the "Boolean"
  16. //        def of "Nlm_Boolean" when it is in public function parameter lists
  17. //
  18.  
  19.  
  20. // need hidden vibrant methods & object for window-system-specific 
  21. #ifdef WIN_MAC
  22. #undef true
  23. #undef false
  24. #endif
  25.  
  26. #include <vibincld.h>
  27.  
  28. #ifdef WIN_MOTIF
  29. extern "C" Nlm_ShellTool Nlm_GetWindowShell PROTO((Nlm_WindoW w));
  30. #endif
  31.  
  32.  
  33. enum ResizeWindSizes {
  34.     kWinDragHeight = 20,
  35.     kWinScrollWidth = 0,   // added to both vert & hor.
  36.     kWinMinWidth = 0,
  37.     kWinExtraHeight
  38. #ifdef WIN_MSWIN
  39.     = 20
  40. #else
  41.     = 0
  42. #endif
  43.     };
  44.  
  45.         /* from vibrant/vibwndws.c */
  46. extern "C" void Nlm_ResizeWindow(Nlm_GraphiC w, Nlm_Int2 dragHeight,
  47.                               Nlm_Int2 scrollWidth, Nlm_Int2 minWidth,
  48.                               Nlm_Int2 extraHeight);
  49.  
  50.  
  51. DWindowManager*    gWindowManager = NULL;
  52.  
  53.  
  54. class DWindowCarcass : public DView
  55. {
  56.     // this object holds the parts of DWindow that cannot be deleted by ~DWindow()
  57.     // because Nlm subview objects are likely in the calling chain.
  58.     // So create this object from a dying window, post to task chain for later
  59.     // trashing by gApplication handler.
  60. //
  61. //   23Dec94 -- this looks obsolete -- needs further test, but
  62. //   simple tests say ~DWindow() is working well w/o it
  63. // !!! NO, MOTIF bombs after ~DWindow() due to calls to windowDeactivate after
  64. //            deleteing window object !
  65. public:
  66.     DWindowCarcass( DView* theWindow) : 
  67.         DView( 0, NULL, 0, NULL, theWindow->fSubordinates)
  68.     {
  69. #ifndef WIN_MOTIF
  70.             // motif bombs in this.delete due to something 
  71.     fNlmObject= theWindow->fNlmObject; // bypass the DView(object) setting
  72. #endif
  73.         theWindow->fNlmObject= NULL;
  74.         theWindow->fSubordinates= NULL;
  75.     }
  76. };
  77.  
  78.  
  79.  
  80.  
  81. // class DWindow
  82.  
  83. extern "C" void windowCloseProc (Nlm_WindoW item)
  84. {
  85.     DWindow *obj= (DWindow*) Nlm_GetObject( (Nlm_GraphiC)item);
  86.     if (obj) obj->Close();
  87. }
  88.  
  89. extern "C" void windowResizeProc (Nlm_WindoW item)
  90. {
  91.     DWindow *obj= (DWindow*) Nlm_GetObject( (Nlm_GraphiC)item);
  92.     if (obj) obj->ResizeWin();
  93. }
  94.  
  95.  
  96. extern "C" void windowActivateProc (Nlm_WindoW item)
  97. {
  98.     DWindow *obj= (DWindow*) Nlm_GetObject( (Nlm_GraphiC)item);
  99.     if (obj) obj->Activate();
  100. }
  101.  
  102. extern "C" void windowDeactivateProc (Nlm_WindoW item)
  103. {
  104.     DWindow *obj= (DWindow*) Nlm_GetObject( (Nlm_GraphiC)item);
  105.     if (obj) obj->Deactivate();
  106. }
  107.  
  108.  
  109.  
  110. DWindow::DWindow(long id, DTaskMaster* itsSuperior, WindowStyles style,
  111.                     short width, short height, short left, short top, char* title, Nlm_Boolean freeOnClose) :
  112.             DView( id, NULL, kWindow, itsSuperior),
  113.             fWindow(NULL), fEditText(NULL),
  114.             fModal(false), fOkay(false), fFreeOnClose(false),
  115.             fPrintHandler(NULL), fSaveHandler(NULL), fFindDlog(NULL)
  116. {
  117.     InitWindow(style, width, height, left, top, title, freeOnClose);
  118. }
  119.  
  120.  
  121. DWindow::DWindow(long id, DTaskMaster* itsSuperior) :
  122.             DView( id, NULL, kWindow, itsSuperior),
  123.             fWindow(NULL), fEditText(NULL),
  124.             fModal(false), fOkay(false), fFreeOnClose(false),
  125.             fPrintHandler(NULL), fSaveHandler(NULL), fFindDlog(NULL)
  126. {
  127.     // caller MUST call: Initialize(style, width, height, left, top, title);
  128. }
  129.  
  130.  
  131. DWindow::~DWindow()
  132. {        
  133. #if 0
  134. // this gets us into trouble when child ~ has been called...
  135. // do in ::Close() instead!
  136.     if (fSaveHandler) {
  137.         char mytitle[50];
  138.         GetTitle(mytitle, sizeof(mytitle));
  139.         if (fSaveHandler->DirtySaveCancelled(mytitle)) 
  140.             ;// can't abort here if they cancel the save 
  141.      }
  142. #endif
  143.  
  144. #ifndef WIN_MOTIF
  145.         // this is working now !! we can throw out that WindowCarcass jazz !!
  146.     Nlm_SetActivate(fWindow, NULL); 
  147.     Nlm_SetDeactivate(fWindow, NULL); // need for motif
  148.  
  149. #if 0
  150.         // also need for motif, to avoid damn call this window's dead draw procs !! 
  151.         // (via nlm_remove->nlm_hidewindow->nlm_update->Xtcallbacks->subview draw methods )
  152.   Nlm_GphPrcsPtr classPtr = Nlm_GetClassPtr((Nlm_GraphiC)fNlmObject);
  153.      classPtr->hide= NULL;
  154. #endif
  155.  
  156. #else
  157.     DWindowCarcass* deadbody= new DWindowCarcass(this);
  158.      gApplication->PostTask( 
  159.         gApplication->newTask( DApplication::kDeleteDeadWindow, DTask::kMenu, (long)deadbody));
  160. #endif
  161.     gWindowManager->DeleteWindow(this, false);
  162. }
  163.                     
  164.                     
  165. void DWindow::InitWindow(WindowStyles style, 
  166.                         short width, short height, short left, short top, char* title, Nlm_Boolean freeOnClose) 
  167. {
  168.     //this->Initialize(); // << this is done in call to DView::DView() 
  169.     fFreeOnClose= freeOnClose;
  170.     switch (style) {
  171.         case document:
  172.             fWindow= Nlm_DocumentWindow(left, top, width, height, title, windowCloseProc, windowResizeProc);
  173.             break;
  174.         case fixed:
  175.             fWindow= Nlm_FixedWindow(left, top, width, height, title, windowCloseProc);
  176.             break;
  177.         case frozen:
  178.             fWindow= Nlm_FrozenWindow(left, top, width, height, title, windowCloseProc);
  179.             break;
  180.         case round:
  181.             fWindow= Nlm_RoundWindow(left, top, width, height, title, windowCloseProc);
  182.             break;
  183.         case alert:
  184.             fWindow= Nlm_AlertWindow(left, top, width, height, windowCloseProc);
  185.             break;
  186.         case modal:
  187.             fWindow= Nlm_ModalWindow(left, top, width, height, windowCloseProc);
  188.             break;
  189.         case floating:
  190.             fWindow= Nlm_FloatingWindow(left, top, width, height, windowCloseProc);
  191.             break;
  192.         case shadow:
  193.             fWindow= Nlm_ShadowWindow(left, top, width, height, windowCloseProc);
  194.             break;
  195.         case plain:
  196.             fWindow= Nlm_PlainWindow(left, top, width, height, windowCloseProc);
  197.             break;
  198.         }
  199.         
  200.     this->SetNlmObject( fWindow);
  201.     Nlm_SetActivate(fWindow, windowActivateProc);
  202.     Nlm_SetDeactivate(fWindow, windowDeactivateProc);
  203.     gWindowManager->AddWindow(this);
  204. }                    
  205.  
  206.  
  207. void DWindow::AddOkayCancelButtons( long okayId, char* okayName, long cancelId, char* cancelName)
  208. {
  209.      Nlm_PoinT npt;
  210.      this->NextSubviewBelowLeft(); // this doesn't account for extra size of DDefaultButton !
  211.      this->GetNextPosition( &npt);
  212.      npt.y += 10;  // is +3 for Mac, +8 for MSWin, +10 for Motif
  213.      this->SetNextPosition( npt);
  214.     DButton* bb= new DButton( cancelId, this, cancelName);
  215.     bb->SetResize( DView::fixed, DView::moveinsuper); // testing, want this??
  216.     bb->suicide(1);
  217.     
  218.     this->NextSubviewToRight();
  219.      this->GetNextPosition( &npt);
  220.      npt.x += 10;  // is +3 for Mac, +8 for MSWin, +10 for Motif
  221.      this->SetNextPosition( npt);
  222.     DDefaultButton* db= new DDefaultButton( okayId, this, okayName);
  223.     db->SetResize( DView::fixed, DView::moveinsuper);
  224.     db->suicide(1);
  225. }
  226.  
  227.  
  228. Nlm_Boolean DWindow::IsMyAction(DTaskMaster* action) 
  229. {    
  230.     // ?? add fEditText cut/copy/paste handling here??
  231.     switch(action->Id()) {
  232.         case cOKAY:
  233.             this->OkayAction();
  234.             fOkay= true;
  235.             // fall thru to next case
  236.         case cCANC: 
  237.             fModal= false;
  238.             this->Close(); // !! Cant Free yet, caller may need object's data !! CloseAndFree();
  239.             return true;
  240.         default:
  241.             return DView::IsMyAction(action);    
  242.         }
  243. }
  244.  
  245. void DWindow::OkayAction() 
  246. }
  247.  
  248. Nlm_Boolean DWindow::PoseModally() 
  249.     fModal = true;
  250.     this->Open();
  251.     while (fModal)  
  252.         gApplication->ProcessTasks();  
  253.     return fOkay; // ?? ain't what we want - want fSubordinate's fId
  254. }
  255.  
  256.  
  257. void DWindow::CalcWindowSize()
  258. {
  259.     Nlm_ResizeWindow( (Nlm_GraphiC)fWindow, kWinDragHeight, kWinScrollWidth,
  260.                          kWinMinWidth, kWinExtraHeight);
  261. }
  262.  
  263. void DWindow::ResizeWin() 
  264. {
  265.     Nlm_PoinT delta;
  266.     Nlm_RecT     current;
  267.     this->ViewRect(current);
  268.             // need to check that fViewrect was set to valid values
  269.     if (fViewrect.bottom>0 && fViewrect.right>0 && fViewrect.top>=0 && fViewrect.left>=0) {
  270.         delta.x = (current.right - current.left) - (fViewrect.right - fViewrect.left);
  271.         delta.y = (current.bottom - current.top) - (fViewrect.bottom - fViewrect.top);
  272.         if (delta.x || delta.y) {
  273.             this->Select(); // for motif ??
  274.             this->ResizeSubviews( this, delta);
  275.             }
  276.         }
  277.     fViewrect= current;
  278.     gWindowManager->SetCurrent(this);
  279. }
  280.  
  281.  
  282. void  DWindow::Select() 
  283. {
  284.     DView::Select();
  285.     //Nlm_UseWindow(fWindow); // 23feb -- does Motif need this also ??
  286.     gWindowManager->SetCurrent(this);
  287. }
  288.  
  289. void DWindow::Open()  
  290. #if 1
  291.     // test order of this, 15may94
  292.     this->Select(); 
  293.     this->Show(); 
  294. #else
  295.     this->Show(); 
  296.     this->Select(); 
  297. #endif
  298.     this->ViewRect(fViewrect); 
  299.     //gWindowManager->SetCurrent(this); // select does
  300. }
  301.  
  302. void DWindow::Hide() 
  303.     DView::Hide(); 
  304.     gWindowManager->UnsetCurrent(this);
  305. }
  306.  
  307. void DWindow::Close() 
  308.     fModal= false;
  309.     if (this != gWindowManager->GetAppWindow()) {
  310.         if (fSaveHandler) {
  311.             char mytitle[50];
  312.             GetTitle(mytitle, sizeof(mytitle));
  313.             if (fSaveHandler->DirtySaveCancelled(mytitle)) 
  314.                 return; 
  315.             }
  316.  
  317.         this->Hide(); 
  318.         if (fFreeOnClose) {
  319.             
  320.                     // We may have a LARGE BUG here... 
  321.                     // looks like DObject::suicide isn't calling destructors of DObject subclasses !!!!!!!!!
  322.                     
  323.             //this->suicide(); 
  324.             //delete this;  << THIS IS BAD programming
  325.             gWindowManager->DeleteWindow(this, true);
  326.             }
  327.         gWindowManager->UnsetCurrent(this);
  328.         }
  329. }
  330.  
  331. void DWindow::CloseAndFree() 
  332.     fModal= false;
  333.     if (this != gWindowManager->GetAppWindow()) {
  334.         gWindowManager->DeleteWindow(this, false); // do so close/hide won't mess w/ win list
  335.         fFreeOnClose= true;
  336.         this->Close(); 
  337.         }
  338. }
  339.  
  340. void DWindow::PrintDoc()  
  341. {
  342.     if (fPrintHandler) fPrintHandler->Print(); 
  343.     else Message(MSG_OK,"DWindow::Print not ready.");
  344. }
  345.  
  346. void DWindow::SaveDoc(DFile* f)  
  347.     if (fSaveHandler) fSaveHandler->Save(f);
  348.     else Message(MSG_OK,"DWindow::Save not ready.");
  349. }
  350.  
  351.  
  352. void DWindow::SendToBack()
  353. {
  354.     gWindowManager->SendToBack(this);
  355. }  
  356.  
  357. void DWindow::BringToFront()
  358. {
  359.     gWindowManager->BringToFront(this);
  360. }  
  361.  
  362. void  DWindow::Activate() 
  363. {
  364.     gWindowManager->SetCurrent(this);
  365. }
  366.  
  367. void  DWindow::Deactivate() 
  368. {
  369.     //gWindowManager->UnsetCurrent(this);
  370. }
  371.  
  372. void DWindow::Erase()         
  373. {
  374.     Nlm_EraseWindow(fWindow); 
  375. }
  376.  
  377. void DWindow::Use()             
  378.     Nlm_UseWindow(fWindow); 
  379.     gWindowManager->SetCurrent(this);
  380. }
  381.  
  382. Nlm_Boolean DWindow::IsUsing() 
  383.     return Nlm_UsingWindow(fWindow); 
  384. }
  385.  
  386. void DWindow::Realize()     
  387.     Nlm_RealizeWindow(fWindow); 
  388. }
  389.  
  390. #if MAC_ONLY_OPTION
  391. Nlm_Boolean DWindow::InFront() 
  392.     return Nlm_InFront(fWindow); 
  393. }
  394. #endif
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401. // DSaveHandler
  402.  
  403. class DSaveDocDialog : public DWindow 
  404. {
  405. public:    
  406.     DSaveDocDialog(char* title);
  407. };
  408.  
  409. DSaveDocDialog::DSaveDocDialog(char* title) :
  410.     DWindow( 0, NULL, DWindow::modal, -10, -10, -50, -20, "", kDontFreeOnClose) // DWindow::fixed
  411. {
  412.     char str[80];
  413.     if (title && *title) {
  414.         StrCpy( str, "Save document '");
  415.     StrNCat( str, title, 20);
  416.     if (StrLen(title)>20) StrCat( str, "...");
  417.     StrCat( str, "'?");
  418.         }
  419.   else
  420.       StrCpy( str, "Save this document?");
  421.     new DPrompt( 0, this, str, 0, 0, Nlm_systemFont);             
  422.     //DButton* but= new DButton( cMapBut, this, "Cancel");
  423.     this->AddOkayCancelButtons(cOKAY,"Yes",cCANC,"No");    
  424.     DWindow::Open();
  425. }
  426.  
  427.  
  428.  
  429. short DSaveHandler::DirtySaveCancelled(char *doctitle) 
  430.     short cancelled= 0;
  431.     if (fDirty) {
  432.         // save/dontsave/cancel;
  433.         DSaveDocDialog* dlog= new DSaveDocDialog(doctitle);
  434.         if (dlog->PoseModally()) { 
  435.             gApplication->DoMenuTask( DApplication::kSaveAs, NULL);
  436.             }
  437.     NotDirty();  // ?? regardless of user choice?
  438.         delete dlog; // <!! not if kFreeOnClose is DWindow option !!
  439.         }
  440.     return cancelled;         // return cancelSave
  441. }
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448. // class DWindowManager
  449.  
  450.  
  451. DWindowManager::DWindowManager()
  452. {
  453.     fWindows= new DList();
  454.     fAppWindow = NULL;
  455.     fLastActive= NULL;
  456. }
  457.  
  458. DWindowManager::~DWindowManager()
  459. {
  460.     long i, n= fWindows->GetSize();
  461.     for (i=0; i<n; i++) { 
  462.         DWindow* theWin= (DWindow*) fWindows->At(i); 
  463.         delete theWin; 
  464.         }
  465.     delete fWindows;
  466. }
  467.  
  468. void DWindowManager::AddWindow(DWindow* theWin)
  469. {
  470.     if (theWin != fAppWindow) {
  471.         fWindows->InsertLast(theWin);
  472.         fLastActive= theWin;
  473.         }
  474. }
  475.  
  476. void DWindowManager::DeleteWindow(DWindow* theWin, Nlm_Boolean postDeleteTask)
  477. {
  478.     if (theWin == fAppWindow) fAppWindow= NULL;
  479.     else if (theWin) {
  480.       fWindows->Delete(theWin); // do before Unset so it isn't stuck back in win list
  481.     UnsetCurrent(theWin);
  482.         // 4sep94: fix to eliminate use of "delete this" in DWindow::Close()
  483.         if (postDeleteTask) delete theWin;  // ~DWindow calls back here, with !postDeleteTask
  484.       }
  485. }
  486.  
  487. void DWindowManager::SetCurrent(DWindow* theWin)
  488. {
  489.     if (theWin && theWin != fAppWindow) {
  490.         if (theWin != (DWindow*)fWindows->Last()) {
  491.             fWindows->Delete(theWin);
  492.             fWindows->InsertLast(theWin);
  493.             }
  494.         fLastActive= theWin;
  495.         }
  496. }
  497.  
  498. void DWindowManager::UnsetCurrent(DWindow* theWin)
  499. {
  500.     if (theWin && theWin == fLastActive) {
  501.         if (theWin == (DWindow*)fWindows->Last()) {
  502.             fWindows->Delete(theWin);
  503.                 //??? where do we put it in list so it cycles to top as real window does
  504.             fWindows->InsertFirst(theWin); 
  505.             }
  506.         fLastActive= (DWindow*)fWindows->Last();
  507.         }
  508. }
  509.  
  510.  
  511. DWindow*    DWindowManager::CurrentWindow() 
  512. {
  513. #if 0
  514. //#ifdef WIN_MAC
  515.     return (DWindow*) Nlm_GetObject( (Nlm_GraphiC)Nlm_FrontWindow());
  516. #else
  517.             // try to get motif to recognize front/active window
  518.     return fLastActive;
  519. #endif
  520. }
  521.  
  522.  
  523.  
  524. void DWindowManager::SendToBack(DWindow* theWin)
  525. {
  526.     if (!theWin) theWin= (DWindow*) fWindows->Last();
  527.     if (theWin) {
  528.         this->UnsetCurrent(theWin);
  529.         
  530. #ifdef WIN_MAC
  531.         Nlm_WindowTool wptr= Nlm_ParentWindowPtr((Nlm_GraphiC)theWin->fWindow);
  532.         if (wptr) ::SendBehind( wptr, NULL);
  533. #endif
  534.  
  535. #ifdef WIN_MSWIN
  536.             // apparently no SendBehind for MSWindows !! 
  537.             // do it the hard way ... bring all others to front
  538.             // this probably looks like shit
  539.             // UnsetCurrent puts theWin == fWindows.First(), so start w/ iwin=1, after 0th
  540.         short nwin= fWindows->GetSize();
  541.         for (short iwin=1; iwin<nwin; iwin++) {
  542.             DWindow* aWin= (DWindow*)fWindows->At(iwin);
  543.         Nlm_WindowTool wptr = Nlm_ParentWindowPtr((Nlm_GraphiC)aWin->fWindow);
  544.            if (wptr) ::BringWindowToTop(wptr);
  545.             }
  546. #endif
  547.  
  548. #ifdef WIN_MOTIF
  549.     if (Nlm_WindowHasBeenShown(theWin->fWindow)) {
  550.       if (Nlm_currentXDisplay != NULL) {
  551.         //Nlm_ShellTool shl;
  552.                 Widget shl; // for IRIX
  553.  
  554.         shl = Nlm_GetWindowShell(theWin->fWindow);
  555.         //XMapRaised (Nlm_currentXDisplay, XtWindow (shl));
  556. #ifndef OS_UNIX_IRIX
  557. // can't get dang sgi to compile w/ XtWindow(Widget) !!
  558.                 XLowerWindow(Nlm_currentXDisplay, XtWindow (shl));
  559. #endif
  560.         }
  561.       }
  562. #endif
  563.  
  564.         theWin= (DWindow*) fWindows->Last();
  565.         theWin->Select();
  566.         }
  567. }
  568.  
  569.  
  570.  
  571. void DWindowManager::BringToFront(DWindow* theWin)
  572. {
  573.      // if null, lastwin
  574.     if (!theWin) {
  575.         theWin= (DWindow*) fWindows->First();
  576.         if (theWin == fAppWindow) theWin= (DWindow*) fWindows->At(1); // skip appwin
  577.         }
  578.     if (theWin) theWin->Select();
  579. }
  580.  
  581.  
  582. void DWindowManager::SetAppWindow(DWindow* theWin)
  583. {
  584.     fAppWindow= theWin;
  585. }
  586.  
  587. DWindow* DWindowManager::GetAppWindow()
  588. {
  589.     return fAppWindow;
  590. }
  591.  
  592.  
  593. Nlm_Boolean    DWindowManager::InWindow(Nlm_PoinT mouse) 
  594.     return Nlm_InWindow(mouse); 
  595. }
  596.  
  597. DWindow*    DWindowManager::WhichWindow(Nlm_PoinT mouse) 
  598. {
  599.     return (DWindow*) Nlm_GetObject( (Nlm_GraphiC)Nlm_WhichWindow(mouse));
  600. }
  601.  
  602.  
  603.     
  604. #ifdef THESE_ARE_REDUNDANT
  605. DWindow*    DWindowManager::FrontWindow() 
  606. {
  607.     return (DWindow*) Nlm_GetObject( (Nlm_GraphiC)Nlm_FrontWindow());
  608. }
  609.  
  610. DWindow*    DWindowManager::ActiveWindow() 
  611. {
  612.     return (DWindow*) Nlm_GetObject( (Nlm_GraphiC)Nlm_ActiveWindow());
  613. }
  614. #endif
  615.  
  616.  
  617. DWindow*    DWindowManager::SavePort(DView* newport) 
  618. {
  619.     Nlm_Handle nlmobject= newport->GetNlmObject();
  620.     return (DWindow*) Nlm_GetObject( (Nlm_GraphiC)Nlm_SavePort(nlmobject));
  621. }
  622.  
  623. void    DWindowManager::RestorePort(DWindow* savedwindow) 
  624. {
  625.     Nlm_RestorePort((Nlm_WindoW) savedwindow->GetNlmObject());
  626. }
  627.  
  628. DDialogText*    DWindowManager::CurrentDialogText() 
  629. {
  630.     return (DDialogText*) Nlm_GetObject( (Nlm_GraphiC)Nlm_CurrentText());
  631. }
  632.  
  633. void    DWindowManager::UpdateDisplays()
  634. {
  635.   Nlm_Update();
  636. }
  637.